/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.univnantes.alma.arbres;


import fr.univnantes.alma.arbres.exceptions.PereRacineException;
import fr.univnantes.alma.arbres.exceptions.PlaceIndisponibleException;
import java.util.Iterator;




/**
 *
 * @author judu
 */
public interface Arbre<T> {

    /**
     * Définit les types d'itération disponibles sur les arbres.
     */
    public static enum ArbreIteratorType {DFS, BFS};

    /**
     *  Cette fonction ajoute un fils en dernière position.
     * @param n : Noeud<T> auquel ajouter le fils
     * @return le Noeud<T> fils nouvellement créé
     */
    public Noeud<T> ajoutFils(Noeud<T> pere) throws PlaceIndisponibleException, NullPointerException;

    public Noeud<T> ajoutFils(Noeud<T> pere, T valeur) throws PlaceIndisponibleException, NullPointerException;

    /**
     *  Place le fils en position pos, ressort exception si place prise
     * @param n Noeud<T> père
     * @param pos   Position du noeud fils
     * @return le noeud créé.
     */
    public Noeud<T> ajoutFilsEnPos(Noeud<T> pere, int pos) throws PlaceIndisponibleException, NullPointerException;

    public Noeud<T> ajoutFilsEnPos(Noeud<T> pere, int pos, T valeur) throws PlaceIndisponibleException, NullPointerException;
    /**
     *
     * @return racine de l’arbre
     */
    public Noeud<T> getRacine();

    /**
     *
     * @param etiquette
     * @return Noeud<T> cherché
     */
    public Noeud<T> getNoeudByEtiquette(int etiquette);

    /**
     *
     * @param n Noeud<T> père
     * @param pos   position du fils voulu
     * @return le fils s’il existe, null sinon.
     */
    public Noeud<T> getFilsByPos(Noeud<T> pere, int pos) throws PlaceIndisponibleException, NullPointerException;

    /**
     * 
     * @param n
     * @return Le père du Noeud<T>
     */
    public Noeud<T> getPere(Noeud<T> fils) throws PereRacineException, NullPointerException;

    /**
     *
     * @param n
     * @return Position du Noeud<T> dans sa fratrie
     */
    public int getPosition(Noeud<T> pere) throws NullPointerException;

    /**
     *
     * @param n
     * @return Frère suivant.
     */
    public Noeud<T> getNextFrere(Noeud<T> pere) throws NullPointerException;

    /**
     *
     * @param n
     * @return Frère précédent.
     */
    public Noeud<T> getPreviousFrere(Noeud<T> pere) throws NullPointerException;


    public Boolean hasNextFrere(Noeud<T> noeud) throws NullPointerException;

    public Boolean hasPreviousFrere(Noeud<T> noeud) throws NullPointerException;

    /**
     * 
     * @param noeud
     * @return
     */
    public Boolean isRacine(Noeud<T> noeud) throws NullPointerException;

    public Noeud<T> getFirstFils(Noeud<T> noeud) throws NullPointerException;

    public Boolean hasFils(Noeud<T> noeud) throws NullPointerException;


    
    public void deleteFils(Noeud<T> noeud) throws NullPointerException;

    /**
     * Supprime un noeud de l'arbre, et tous ses fils
     *
     * @param noeud
     * @throws NullPointerException
     */
    public void deleteNoeud(Noeud<T> noeud) throws NullPointerException;

    public Iterator<Noeud<T>> iterator();

    /**
     * Cette méthode prend deux valeur possibles en paramêtre :
     * "DFS" et "BFS". En fonction de la valeur, on appelle soit iteratorBFS, soit iteratorDFS
     * @param typeIt
     * @return Iterator
     */
    public Iterator<Noeud<T>> iterator(ArbreIteratorType typeIt);

    public Iterator<Noeud<T>> iteratorBFS();

    public Iterator<Noeud<T>> iteratorDFS();

}
